#!/usr/bin/env python
# -*—coding:utf8-*-
# @author: flame
# @file: WebServer.py
# @time: 2023/11/15 14:46

import socket
import threading
import json


class WebServer:

    def __init__(self):
        self.Students_list = []
        self.File_Path = 'students_management.txt'
        self.__load_data(self.File_Path)

    # 启动服务器的函数
    def startServer(self):
        # 创建一个socket 对象
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置复用端口
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 绑定IP与端口, 参数是一个元组，IP是字符串，端口是数字
        server.bind(("", 8888))
        # 启动服务器的监听
        server.listen(256)
        print("MyWebServer String On 127.0.0.1:8888")
        # 使用死循环接受客户端的请求
        while True:
            # 接收客户端的连接，返回客户端的socker对象和IP_port
            client, ip_port = server.accept()
            print(f"客户端  {ip_port[0]} 使用 {ip_port[1]} 端口连接成功")
            # 创建一个子线程去处理客户端的请求，主线程再去接受其它客户端的请求
            t = threading.Thread(target=self.handleClientRequest, args=(client,))
            # 设置守护线程
            t.daemon = True
            # 启动子线程去处理客户端请求
            t.start()

    # 用来处理用户请求的函数
    def handleClientRequest(self, client):
        # 读取客户端的请求内容
        recv_data = client.recv(4096).decode("utf-8")
        # 判断与客户端的连接是否断开
        if len(recv_data) == 0:
            client.close()
            return
        # 解析客户端请求数据
        request = self.parseRequest(recv_data)
        # 根据用户请求去做相应的处理，不同的请求使用不同的函数进行处理，这个处理函数称为接口，找接口的过程，称为路由
        response = self.router(request)
        # 服务器将响应数据返回给客户端
        client.send(response)
        # 服务器为客户端 提供一次服务完成，关闭连接
        client.close()

    # 用来解析请求报文的函数
    def parseRequest(self, recv_data):
        # 用来保存数据的字典
        request = {
            "method": "",
            "path": "",
            "values": {}
        }
        # 先获取到第一行请求行数据
        recv_data = recv_data.split()
        # 保存请求方法
        request["method"] = recv_data[0]
        # 处理请求路径 和参数
        path = recv_data[1]
        if "?" in path:
            tmp = path.split("?")
            # 保存路径
            path = tmp[0]
            # 提取参数
            params = tmp[1].split("&")
            for s in params:
                if s != '':
                    # 分解析查询参数字符串
                    k, v = s.split("=")
                    request["values"][k] = v
        # 保存请求路径
        request["path"] = path
        # 返回解析结果
        return request

    def router(self, request):
        # 取出客户端 的请求路径
        path = request.get("path")
        values = request.get("values")
        # 使用 if 实现一个简单的路由
        response_body = ""
        if path == "/add":
            response_body = self.add(values)
        elif path == "/change":
            response_body = self.change(values)
        elif path == "/query":
            response_body = self.query(values)
        elif path == "/del":
            response_body = self.delete(values)
        else:
            response_body = self.error()

        # 拼装完整的响应报文
        response = "HTTP/1.1 200 OK\r\n"
        # image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
        response += "Content-Type: json;charset=utf-8\r\n"
        response += "Server: MyWebServer V1.0\r\n"
        response += "\r\n"
        # 因为使用的是TCP字节流传输数据，所以要对响应数据进行转换类型
        response = response.encode("utf-8")
        response += json.dumps(response_body).encode("utf-8")
        # response += response_body

        print(response)
        return response

    def add(self, values):
        try:
            for stu in self.Students_list:
                if values['sid'] == stu['sid']:
                    return {'msg': '当前添加的学号已经存在'}
            else:
                tmp_stu = {'sid': values['sid'], 'name': values['name'], 'age': values['age'],
                           'gender': values['gender']}
                self.Students_list.append(tmp_stu)
                self.__write_data(self.File_Path)
                return {'msg': '新增成功'}
        except Exception:
            return {'msg': '缺少传参'}

    def change(self, values):
        index = 0
        try:
            for i in self.Students_list:
                if values["sid"] == i['sid']:
                    self.Students_list[index]['name'] = values['name']
                    self.Students_list[index]['age'] = values['age']
                    self.Students_list[index]['gender'] = values['gender']
                    self.__load_data(self.File_Path)
                    return {'msg': '修改成功'}
                else:
                    index += 1

            if index == len(self.Students_list):
                return {'msg': '修改失败：该学生系统无该学号学生'}
        except Exception:
            return {'msg': '缺少传参'}

    def query(self, values):
        try:
            for stu in self.Students_list:
                if values['sid'] == stu['sid']:
                    return stu
            else:
                return {'msg': '根据对应学号无法查询到对应数据'}
        except Exception:
            return {'msg': '传参缺少sid'}

    def delete(self, values):
        index = 0
        try:
            for i in self.Students_list:
                if values["sid"] == i['sid']:
                    del self.Students_list[index]
                    self.__write_data(self.File_Path)
                    return {'msg': '删除成功'}
                else:
                    index += 1

            if index == len(self.Students_list):
                return {'msg': '删除失败：该学生系统无该学号学生'}
        except Exception:
            return {'msg': '缺少传参'}
        pass

    def error(self):
        return {'msg': '不存在对应的请求地址'}

    def __load_data(self, path):
        # 文件格式如下
        # 001, 张三, 15, 男
        # 002, 丽丝, 17, 女
        # 003, 王五, 18, 男
        # 004, 张三, 19, 男
        with open(path, mode='r', encoding='utf-8') as file:
            for line in file.readlines():
                tmp = line.splitlines()[0].split(',')
                stu_tmp = {'sid': tmp[0], 'name': tmp[1], 'age': int(tmp[2]), 'gender': tmp[3]}
                self.Students_list.append(stu_tmp)
            file.close()

    def __write_data(self, path):
        with open(path, mode='w', encoding='utf-8') as file:
            for stu in self.Students_list:
                tmp_str = stu["sid"] + ',' + stu["name"] + ',' + str(stu["age"]) + ',' + stu["gender"] + '\n'
                file.write(tmp_str)
            file.close()


if __name__ == '__main__':
    WebServer().startServer()